/**
 *
 */
package platform.common.dao.impl;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.poi.hssf.record.formula.functions.T;
import org.hibernate.CacheMode;
import org.hibernate.Query;
import org.hibernate.ScrollMode;
import org.hibernate.ScrollableResults;
import org.springframework.util.Assert;

import platform.common.bo.Page;
import platform.common.dao.IDomainProvider;
import platform.util.TokenUtil;

/**
 * @author daizs
 *
 */
public class DaoImpl extends NestSetTreeDaoImpl {
	/**
	 *
	 * <br/>方法描述:执行动态hql
	 *
	 * @param queryName
	 *            hql别名(领域提供者get后面一段)
	 * @param dynamicMap
	 *            动态构造hql的参数
	 * @param hqlParamMap
	 *            为hql语句赋值
	 * @throws DaoConfigException
	 */
	@SuppressWarnings("unchecked")
	public void exeDynamicHql(IDomainProvider domainProvider, String queryName,
			Map dynamicMap, Map hqlParamMap) throws DaoException,DaoConfigException {
		String hql = getDynamicHqlByDomainAndName(domainProvider, queryName,dynamicMap);
		try {
			Query query = this.getSession().createQuery(hql);
			if (hqlParamMap != null) {
				addArgs(hqlParamMap, query);
			}
			query.executeUpdate();
		} catch (Exception e) {
			throw this.handleDaoException(e);
		}
	}
	@SuppressWarnings("unchecked")
	public void exeDynamicHql(String queryName,	Map dynamicMap, Map hqlParamMap) throws DaoException,
			DaoConfigException {
		String hql = getDynamicHqlByDomainAndName((IDomainProvider)this, queryName,dynamicMap);
		try {
			Query query = this.getSession().createQuery(hql);
			if (hqlParamMap != null) {
				addArgs(hqlParamMap, query);
			}
			query.executeUpdate();
		} catch (Exception e) {
			throw this.handleDaoException(e);
		}
	}

	/**
	 *
	 * <br/>方法描述:依据动态hql查询
	 *
	 * @param queryName
	 *            hql别名(领域提供者get后面一段)
	 * @param dynamicMap
	 *            动态构造hql的参数
	 * @param hqlParamMap
	 *            为hql语句赋值
	 * @throws DaoConfigException
	 */
	@SuppressWarnings({ "unchecked", "hiding" })
	public <T>T findByDynamicHql(IDomainProvider domainProvider,String queryName, Map<String,Object> dynamicMap, Map<String,Object> hqlParamMap)
			throws DaoException, DaoConfigException {
		String hql = getDynamicHqlByDomainAndName(domainProvider, queryName,dynamicMap);
		T result = null;
		try {
			if (!hqlParamMap.isEmpty()) {
				result = (T)getHibernateTemplate().find(hql, hqlParamMap);
			} else {
				result = (T)getHibernateTemplate().find(hql);
			}
		} catch (Exception e) {
			log.error("", e);
			throw this.handleDaoException(e);
		}
		return result;
	}
	
	@SuppressWarnings({ "unchecked", "hiding" })
	public <T>T findByDynamicHql(String queryName, Map<String,Object> dynamicMap, Map<String,Object> hqlParamMap)throws DaoException, DaoConfigException {
		String hql = getDynamicHqlByDomainAndName((IDomainProvider)this, queryName,dynamicMap);
		T result = null;
		try {
			if (!hqlParamMap.isEmpty()) {
				result = (T)getHibernateTemplate().find(hql, hqlParamMap);
			} else {
				result = (T)getHibernateTemplate().find(hql);
			}
		} catch (Exception e) {
			log.error("", e);
			throw this.handleDaoException(e);
		}
		return result;
	}

	/**
	 * 以服务器端游标的方式查询
	 *
	 * @param domainProvider 领域提供者
	 * @param queryName 查询定义别名
	 * @param qryParams 查询参数数组
	 * @return 领域列表的服务器端游标
	 * @throws DaoException, DaoConfigException
	 */
	public ScrollableResults findScrollableResultsByHqlNameAndDomian(
			IDomainProvider domainProvider, String queryName, Object[] qryParams)
			throws DaoException, DaoConfigException {
		String hql = getHqlByDomainAndName(domainProvider, queryName);
		try {
			Query query = this.getSession().createQuery(hql);
			//TODO 依据参数数组为query赋值参数
			return query.setCacheMode(CacheMode.IGNORE) .scroll(ScrollMode.FORWARD_ONLY);

		} catch (Exception e) {
			throw this.handleDaoException(e);
		}

	}

	/**
	 * 依据领域名称和查询定义别名查询记录
	 *
	 * @param domainProvider 领域提供者
	 * @param queryName 查询定义别名
	 * @param qryParams 查询参数Map
	 * @return 领域列表的服务器端游标
	 * @throws DaoException, DaoConfigException
	 */
	@SuppressWarnings("unchecked")
	public ScrollableResults findScrollableResultsByHqlNameAndDomian(
			IDomainProvider domainProvider, String queryName, Map qryParamMap)
			throws DaoException, DaoConfigException {
		String hql = getHqlByDomainAndName(domainProvider, queryName);

		try {
			Query query = this.getSession().createQuery(hql);
			if (qryParamMap != null) {
				addArgs(qryParamMap, query);
			}
			return query.setCacheMode(CacheMode.IGNORE) .scroll(ScrollMode.FORWARD_ONLY);
		} catch (Exception e) {
			throw this.handleDaoException(e);
		}

	}
	@SuppressWarnings("unchecked")
	public Map findByHqlNameAndDomianByPageWithoutAttentionSelectCauseContent(IDomainProvider domainProvider, String queryName, Map qryParamMap,
			int startPos, int recordNum) throws DaoException, DaoConfigException {
		Map map=new HashMap();		
		String hql = getHqlByDomainAndName(domainProvider, queryName);
		
	    StringBuffer sb=new StringBuffer();
	    int  index=TokenUtil.getIndex(hql);
	    sb.append(" select count(*) ").append(hql.substring(index));
	    Query query=null;
	    query=getSession().createQuery(removeOrders(removeFetch(sb.toString())));
	    addArgs(qryParamMap, query);
		Object obj= query.uniqueResult();
		if(null!=obj){
			Long objLong = (Long)obj;
			map.put("sum", objLong.intValue());
		}else{
			map.put("sum", 0);
		}
		 query = this.getSession().createQuery(hql).setFirstResult(
				startPos).setMaxResults(recordNum);
		addArgs(qryParamMap, query);
		map.put("list", query.list());
		return map;
	}	
	/**
	 * 去掉Hql中Order By子句
	 * @param hql  hql语句
	 * @return	hql语句
	 */
	private static String removeOrders(String hql) {
		Assert.hasText(hql);
		Pattern p = Pattern.compile("order\\s*by[\\w|\\W|\\s|\\S]*",
				Pattern.CASE_INSENSITIVE);
		Matcher m = p.matcher(hql);
		StringBuffer sb = new StringBuffer();
		while (m.find()) {
			m.appendReplacement(sb, "");
		}
		m.appendTail(sb);
		return sb.toString();
	}
	/**
	 * 替换Hql中的fetch(查询Count时不能同时出现fetch,这是Hql的语法)
	 * @param hql hql语句
	 * @return	hql语句
	 */
	private String removeFetch(String hql) {
		return hql.replace("join fetch", "join");
	}
	/**
	 *
	 * <br/>方法描述:依据动态hql查询
	 *
	 * @param queryName
	 *            hql别名(领域提供者get后面一段)
	 * @param dynamicMap
	 *            动态构造hql的参数
	 * @param hqlParamMap
	 *            为hql语句赋值
	 * @param page
	 *            分页信息
	 * @throws DaoConfigException
	 */
	@SuppressWarnings("unchecked")
	public List findByDynamicHql(IDomainProvider domainProvider,
			String queryName, Map dynamicMap, Map hqlParamMap,Page page)
	throws DaoException, DaoConfigException {
		String hql = getDynamicHqlByDomainAndName(domainProvider, queryName,
				dynamicMap);
		List result = null;
		try {
			Query query = this.getSession().createQuery(hql);
			query.setCacheable(true);
			
			if (hqlParamMap != null) {
				addArgs(hqlParamMap, query);
			}
			if (page.getPageNo() > 0 && page.getPageSize() > 0) {
				query.setFirstResult((page.getPageNo() - 1)
						* page.getPageSize());
				query.setMaxResults(page.getPageSize());
			}
			result = query.list();
		} catch (Exception e) {
			throw this.handleDaoException(e);
		}
		return result;
	}
	
	/**
	 *
	 * <br/>方法描述:依据动态hql查询
	 *
	 * @param queryName
	 *            hql别名(领域提供者get后面一段)
	 * @param dynamicMap
	 *            动态构造hql的参数
	 * @param hqlParamMap
	 *            为hql语句赋值
	 * @param page
	 *            分页信息
	 * @throws DaoConfigException
	 */
	@SuppressWarnings("unchecked")
	public List findByDynamicHql(String queryName, Map dynamicMap, Map hqlParamMap,Page page)throws DaoException, DaoConfigException {
		String hql = getDynamicHqlByDomainAndName((IDomainProvider)this, queryName,dynamicMap);
		List result = null;
		try {
			Query query = this.getSession().createQuery(hql);
			query.setCacheable(true);
			if (hqlParamMap != null) {
				addArgs(hqlParamMap, query);
			}
			if (page.getPageNo() > 0 && page.getPageSize() > 0) {
				query.setFirstResult((page.getPageNo() - 1)
						* page.getPageSize());
				query.setMaxResults(page.getPageSize());
			}
			result = query.list();
		} catch (Exception e) {
			throw this.handleDaoException(e);
		}
		return result;
	}
}
